import pathlib
import time
import re
import typing
import os
import yaml
import ctypes
import psutil
import subprocess
import requests
import winsound
import datetime
import rich
from selenium.webdriver.edge.webdriver import WebDriver
from selenium.webdriver.edge.service import Service
from selenium.webdriver.edge.options import Options
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
from selenium.common.exceptions import *


def print_with_time(*args, **kwargs) -> None:
    """在输出内容前添加当前时间戳，使用rich.print进行格式化输出
    
    功能：在所有输出内容前自动添加当前本地时间，时间格式为YYYY-MM-DD HH:MM:SS
    时间会以蓝色加粗样式显示，其余内容保持rich的默认格式化特性
    
    Args:
        *args: 任意数量的位置参数，将被原样传递给rich.print
        **kwargs: 任意关键字参数，将被原样传递给rich.print
    
    Example:
        >>> print_with_time("系统启动完成")
        [bold blue][2025-08-07 16:45:30][/bold blue] 系统启动完成
        
        >>> print_with_time("操作结果：", "[green]成功[/green]")
        [bold blue][2025-08-07 16:46:10][/bold blue] 操作结果：[green]成功[/green]
    """
    # 获取当前时间并格式化为字符串
    current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    # 拼接时间前缀与输出内容并打印
    rich.print(f"[bold blue][{current_time}][/bold blue]", *args, **kwargs)


def Checkout_Debug_Mode_Activate() -> bool:
    """
    检查调试模式路径是否可用

    Returns: 
        bool: 如果调试模式路径可用，则返回 True，否则返回 False

    Example:
        >>> MyEdge.CheckOutDebugModePath()
        True
    """
    url = "http://127.0.0.1:9652/json/version"
    try:
        response = requests.get(url=url)
        if response.status_code == 200:
            result = True
        else:
            result = False
    except Exception as e:
        print_with_time(f"请求调试模式路径时发生错误: {e}")
        result = False
    return result


def Fast_Create_WebDriver_Wait_Action() -> WebDriver:
    """快速创建 WebDriver 实例。

    Returns:
        typing.Tuple[WebDriver, WebDriverWait, ActionChains]: 返回 WebDriver、WebDriverWait 和 ActionChains 实例的元组。
    """
    options = Options()
    options.add_experimental_option("debuggerAddress", "127.0.0.1:9652")
    service = Service()
    driver = WebDriver(options=options, service=service)
    return driver


def Goto_CurrentActivateUrl(driver: WebDriver) -> None:
    """使用 requests 获取当前激活的页面的 url,并切换到当前激活的页面.

    Args:
        driver (WebDriver): WebDriver 实例

    Returns:
        _type_: None
    """
    debug_json_data = requests.get(
        url="http://127.0.0.1:9652/json", timeout=5).json()

    # 判断获取回来的数据是否正确
    if not isinstance(debug_json_data, list):
        print_with_time("接口返回数据格式不正确（非列表或为空）")
        return None

    # 过来掉不需要的 page 页面
    filter_json_data = list(
                                    filter(lambda item: (
                                        item['type'] == "page" and
                                        not item['title'].lower().startswith("devtools") and
                                        not item['title'].lower().startswith("offscreen") and
                                        not item['title'].lower().startswith("新标签页") and
                                        not item['url'].lower().startswith("edge://newtab/") and
                                        not item['url'].lower().startswith("chrome-extension") and
                                        not item['url'].lower().startswith("chrome-devtools")
                                    ), debug_json_data)
                                )
    current_activate_handle = filter_json_data[0]['id']
    driver.switch_to.window(current_activate_handle)


def Goto_CurrentActivateUrl_old(driver: WebDriver) -> None:
    """使用 uiautomation 获取当前激活的浏览器的 handle 并切换到对应的标签页

    Args:
        driver (WebDriver): WebDriver 实例

    Returns:
        _type_: None
    """
    import uiautomation
    root = uiautomation.GetRootControl()
    window_control = root.WindowControl(RegexName='.*?Microsoft.*?Edge')
    url_control = window_control.ToolBarControl(
        Name='应用栏').EditControl(Name='地址和搜索栏')
    current_activate_url = url_control.GetValuePattern().Value.replace("\"", "%22")

    if driver.current_url == current_activate_url or driver.current_url[:-1] == current_activate_url:
        return
    else:
        # print_with_time(f"提示 : 当前页面的 handle 对应的 url 是 : {driver.current_url}")
        for handle in driver.window_handles:
            driver.switch_to.window(window_name=handle)
            if driver.current_url == current_activate_url or driver.current_url[:-1] == current_activate_url:
                print_with_time(
                    f"提示 : 切换完成!当前页面的 handle 对应的 url 是 : {driver.current_url}")
                break


def Checkout_Has_Msedge_Process(_process_name: str = "msedge.exe"):
    """检查是否存在指定名称的进程
        
        Args:
            _process_name (str): 进程名称
        
        Returns:
            bool: 如果存在指定名称的进程，则返回 True，否则返回 False
        
        Example:
            >>> CheckMsEdgeProcess('msedge.exe')
            True
        """
    _is_process_running = False
    for _proc in psutil.process_iter(['name']):
        if _proc.info['name'] == _process_name:
            _is_process_running = True
            break
    return _is_process_running


def Close_All_Msedge_Process(_process_name: str = "msedge.exe") -> bool:
    """
    关闭所有指定名称的进程

    Args:
        _process_name (str): 进程名称

    Returns:
        bool: 如果成功关闭所有指定名称的进程，则返回 True，否则返回 False

    Example:
        >>> MyEdge.CloseAllMsEdgeProcess('msedge.exe')
        True
    """
    success = True  # 初始化返回值
    for proc in psutil.process_iter(['pid', 'name']):
        if _process_name == proc.info['name']:
            try:
                proc.kill()  # 关闭进程
                print_with_time(
                    f"Closed Microsoft Edge process with PID: {proc.info['pid']}")
            except Exception as e:
                print_with_time(
                    f"Failed to close Microsoft Edge process with PID: {proc.info['pid']}. Error: {e}")
                success = False  # 如果关闭失败，设置返回值为 False
    return success


def Start_Debugmode_Browser(_edge_path: str = "C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe", _port: int = 9652):
    """启动调试模式浏览器

    Args:
        _edge_path (str): Edge 浏览器的路径
        _port (int): 启动调试模式的端口号
    """
    # 定义启动命令
    command = rf'"{_edge_path}" --remote-debugging-port={_port} --disable-extensions "http://127.0.0.1:9652/json/version"'

    # 启动新的进程
    CREATE_NEW_CONSOLE = 0x00000010
    subprocess.Popen(command, shell=True, creationflags=CREATE_NEW_CONSOLE)


def Start_Debugmode_Browser_With_Extensions(_edge_path: str = "C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe", _port: int = 9652):
    # 定义启动命令
    command = rf'"{_edge_path}" --remote-debugging-port={_port} "http://127.0.0.1:9652/json/version"'

    # 启动新的进程
    CREATE_NEW_CONSOLE = 0x00000010
    subprocess.Popen(command, shell=True, creationflags=CREATE_NEW_CONSOLE)


def Custom_Message(parent_hwnd: int = 0, title: str = 'default_title', text: str = 'default_text', type: int = 0) -> int:
    """
    显示自定义消息框。

    该函数通过 ctypes 调用 Windows API 来显示一个带有自定义内容和标题的消息框。
    可以用于快速在 Windows 应用程序中创建消息提示。

    Args:
        parent_hwnd (int): 父窗口的窗口句柄。默认值为 0，表示没有父窗口。
        title (str): 消息框的标题。默认值为 'default_title'。
        text (str): 消息框的内容。默认值为 'default_text'。
        type (int): 消息框的类型，决定了消息框的样式和按钮。默认值为 0。

    Returns:
        int: 用户点击消息框按钮后返回的值，表示用户的选择。
    """
    return ctypes.windll.user32.MessageBoxW(parent_hwnd, text, title, type)


def Fast_Create_WebDriver_Wait_Action() -> WebDriver:
    """快速创建 WebDriver、WebDriverWait 和 ActionChains 实例。

    Returns:
        typing.Tuple[WebDriver, WebDriverWait, ActionChains]: 返回 WebDriver、WebDriverWait 和 ActionChains 实例的元组。
    """
    options = Options()
    options.add_experimental_option("debuggerAddress", "127.0.0.1:9652")
    service = Service()
    driver = WebDriver(options=options, service=service)
    return driver
